"use strict";
const assert = require('assert');
const co = require("co");
const md5 = require("blueimp-md5");

const g = require("../global.js");
const Service = require("../service.js");
const Room = require("../entity/Room.js");
const Card = require("../entity/Card.js");
const Action = require("../entity/Action.js");

const devStatus = g.DEV_STATUS_UNITTEST;
const SALT = "g9ByuRar0vJkW8sc";
process.on('unhandledRejection', () => {});
process.on('rejectionHandled', () => {});
describe("微信登录后", function() {
    let db;
    let service;
    let userInfo1, userInfo2, userInfo3, userInfo4, userInfo5, userInfo6, userInfo7;
    before((done) => {
        co(function*() {
            service = yield Service.create(devStatus);
            db = yield service.initDb();
            assert.notEqual(db, null);
            //清理数据
            yield db.collection(g.colls.users).deleteMany({});
            yield db.collection(g.colls.rooms).deleteMany({});
            yield db.collection(g.colls.logs).deleteMany({});
            yield db.collection(g.colls.cards).deleteMany({});
            yield db.collection(g.colls.actions).deleteMany({});
            yield db.collection(g.colls.games).deleteMany({});
            yield db.collection(g.colls.gangs).deleteMany({});
            yield db.collection(g.colls.hupais).deleteMany({});
            yield db.collection(g.colls.records).deleteMany({});
            yield db.collection(g.colls.recordDetails).deleteMany({});
            yield db.collection(g.colls.agents).deleteMany({});
            //创建用户
            userInfo1 = yield service.wxLogin("1", "192.168.0.1");
            assert.equal(userInfo1.data.user.ip, "192.168.0.1");
            //连续登录2次，也应该一样
            userInfo1 = yield service.wxLogin("1", "192.168.0.1");
            assert.equal(userInfo1.data.user.ip, "192.168.0.1");
            userInfo2 = yield service.wxLogin("2", "192.168.0.2");
            userInfo3 = yield service.wxLogin("3", "192.168.0.3");
            userInfo4 = yield service.wxLogin("4", "192.168.0.4");
            userInfo7 = yield service.wxLogin("7", "192.168.0.7");
            //给用户1冲100张卡
            yield db.collection(g.colls.users).updateOne({
                unionid: "1"
            }, {
                $set: {
                    roomCard: 100
                }
            });
            yield db.collection(g.colls.users).updateOne({
                unionid: "2"
            }, {
                $set: {
                    roomCard: 0
                }
            });
            //给用户3冲100张卡
            yield db.collection(g.colls.users).updateOne({
                unionid: "3"
            }, {
                $set: {
                    roomCard: 100
                }
            });
            //这个用户没有登录
            yield db.collection(g.colls.users).insertOne({
                unionid: "6"
            });
            done();
        }).catch((err) => {
            done(err);
        });
    });
    it("设置密码", (done) => {
        co(function*() {
            yield service.setPassword(userInfo2.data.session, "123");
            let agents = yield db.collection(g.colls.agents).find().toArray();
            assert.equal(agents.length, 1);
            assert.equal(agents[0].password, md5("123", SALT));
            yield service.setPassword(userInfo2.data.session, "1234");
            agents = yield db.collection(g.colls.agents).find().toArray();
            assert.equal(agents.length, 1);
            assert.equal(agents[0].password, md5("1234", SALT));
            done();
        }).catch((err) => {
            done(err);
        });
    });
    describe("创建房间", () => {
        it("用户未登录", (done) => {
            co(function*() {
                yield service.createRoom("", {
                    mode: 1
                });
                done("应该要抛出用户未登录的错误");
            }).catch((err) => {
                if (err.errcode == 101) {
                    done();
                } else {
                    done(err);
                }
            });
        });
        describe("设置session后", () => {
            describe("成功登陆后", (done) => {
                it("房卡数量不足", (done) => {
                    co(function*() {
                        yield service.createRoom(userInfo2.data.session, {
                            mode: 1
                        });
                        done("应该要抛出房卡数量不足的错误");
                    }).catch((err) => {
                        if (err.errcode == 201) {
                            done();
                        } else {
                            done(err);
                        }
                    });
                });
                describe("成功创建房间", (done) => {
                    let room;
                    before((done) => {
                        co(function*() {
                            let result = yield service.createRoom(userInfo1.data.session, {
                                mode: 1
                            });
                            assert.equal(result.method, "createRoom");
                            room = result.data;
                            done();
                        }).catch((err) => {
                            done(err);
                        });
                    });
                    it("现在有一个房间了", (done) => {
                        co(function*() {
                            let rooms = yield db.collection(g.colls.rooms).find({}).toArray();
                            assert.equal(rooms.length, 1);
                            done();
                        }).catch((err) => {
                            done(err);
                        });
                    });
                    it("房号要大于0小于1000000", () => {
                        assert.deepEqual(room.number > 0 && room.number < 1000000, true);
                    });
                    it("用户的房卡数量不变", (done) => {
                        co(function*() {
                            let user = yield db.collection(g.colls.users).findOne({
                                unionid: "1"
                            });
                            assert.deepEqual(user.roomCard, 100);
                            done();
                        }).catch((err) => {
                            done(err);
                        });
                    });
                });
            });

        });
    });
    describe("创建房间后", () => {
        let room;
        beforeEach((done) => {
            co(function*() {
                //清除用户创建的房间
                yield db.collection(g.colls.users).updateMany({}, {
                    $unset: {
                        roomNumber: 0,
                        point: 0,
                        roomDirection: 0
                    }
                });
                yield db.collection(g.colls.rooms).deleteMany({});
                let result = yield service.createRoom(userInfo1.data.session, {
                    mode: 1
                });
                room = result.data;
                done();
            }).catch((err) => {
                done(err);
            });
        });
        describe("断线重连", () => {
            it("如果用户没有加入房间，直接返回用户信息", (done) => {
                co(function*() {
                    yield service.joinRoom(userInfo2.data.session, room.number);
                    yield service.joinRoom(userInfo3.data.session, room.number);
                    let result = yield service.reconnect(userInfo1.data.session, "ip ip");
                    assert.equal(result.data.user.ip, "ip ip");
                    assert.equal(result.method, "reconnect");
                    assert.equal(result.data.user.unionid, "1");
                    //如果加入了房间，要给其他人发送通知
                    assert.equal(result.notifies[0].data.unionid, "1", "通知别人自己重连的信息");
                    assert.equal(result.notifies[1].data.unionid, "1", "通知别人自己重连的信息");
                    assert.equal(result.notifies[0].to, "2", "通知别人");
                    assert.equal(result.notifies[1].to, "3", "通知别人");
                    //如果在牌局中，需要返回牌局的信息
                    result = yield service.joinRoom(userInfo4.data.session, room.number);
                    result = yield service.reconnect(userInfo1.data.session, "ip ip");
                    assert.notEqual(result.data.gameInfo.cards, null, "要有牌");
                    assert.notEqual(result.data.gameInfo.actions, null, "要有可以进行的操作");
                    done();
                }).catch((err) => {
                    done(err);
                });
            });
            it("如果已经有了牌局，要返回牌局信息", (done) => {
                co(function*() {
                    yield service.joinRoom(userInfo2.data.session, room.number);
                    yield service.joinRoom(userInfo3.data.session, room.number);
                    yield service.joinRoom(userInfo4.data.session, room.number);
                    let result = yield service.reconnect(userInfo4.data.session, "ip ip");
                    assert.equal(result.data.gameInfo.users.length, 3);
                    done();
                }).catch((err) => {
                    done(err);
                });
            });
        });
        describe("解散房间", () => {
            it("用户没有房间", (done) => {
                co(function*() {
                    yield service.dismissRoom(userInfo3.data.session, 123456);
                    assert.fail("应该要抛出用户没有房间的异常");
                }).catch((err) => {
                    if (err.errcode == 201) {
                        done();
                    } else {
                        done(err);
                    }
                });
            });
            it("房间不存在", (done) => {
                co(function*() {
                    yield service.joinRoom(userInfo2.data.session, 123456);
                    yield service.dismissRoom(userInfo2.data.session);
                    assert.fail("应该要抛出房间不存在的异常");
                }).catch((err) => {
                    if (err.errcode == 202) {
                        done();
                    } else {

                        done(err);
                    }
                });
            });
            it("解散房间需要把所有的牌清空", (done) => {
                co(function*() {
                    yield service.joinRoom(userInfo2.data.session, room.number);
                    yield service.joinRoom(userInfo3.data.session, room.number);
                    yield service.joinRoom(userInfo4.data.session, room.number);
                    let cards = yield db.collection(g.colls.cards).find({
                        roomNumber: room.number
                    }).toArray();
                    assert.equal(cards.length, 104);
                    yield service.voteDismissRoom(userInfo1.data.session, true);
                    yield service.voteDismissRoom(userInfo2.data.session, true);
                    yield service.voteDismissRoom(userInfo3.data.session, true);
                    cards = yield db.collection(g.colls.cards).find({
                        roomNumber: room.number
                    }).toArray();
                    assert.equal(cards.length, 0);
                    done();
                }).catch((err) => {
                    done(err);
                });
            });
            it("解散房间要把房间相关的所有用户的action清空", (done) => {
                co(function*() {
                    yield service.joinRoom(userInfo2.data.session, room.number);
                    yield service.joinRoom(userInfo3.data.session, room.number);
                    yield service.joinRoom(userInfo4.data.session, room.number);
                    yield service.voteDismissRoom(userInfo1.data.session, true);
                    yield service.voteDismissRoom(userInfo2.data.session, true);
                    yield service.voteDismissRoom(userInfo3.data.session, true);
                    let actions = yield db.collection(g.colls.actions).find({
                        roomNumber: room.number
                    }).toArray();
                    assert.equal(actions.length, 0);
                    done();
                }).catch((err) => {
                    done(err);
                });

            });
            it("解散房间成功", (done) => {
                co(function*() {
                    yield service.joinRoom(userInfo2.data.session, room.number);
                    let dismissResult = yield service.dismissRoom(userInfo1.data.session);
                    assert.equal(dismissResult.notifies[0].to, "2");
                    assert.equal(dismissResult.notifies[0].method, "onDismissRoom");
                    assert.equal(dismissResult.notifies[0].data.roomNumber, room.number);
                    assert.equal(dismissResult.method, "dismissRoom");
                    let user = yield db.collection(g.colls.users).findOne({
                        unionid: "1"
                    });
                    let user2 = yield db.collection(g.colls.users).findOne({
                        unionid: "2"
                    });
                    assert.equal(user.roomNumber, null);
                    assert.equal(user.point, null);
                    assert.equal(user.direction, null);
                    assert.equal(user2.roomNumber, null);
                    assert.equal(user2.point, null);
                    assert.equal(user2.direction, null);
                    done();
                }).catch((err) => {
                    done(err);
                });
            });
        });
        describe("加入房间", () => {
            before((done) => {
                co(function*() {
                    yield db.collection(g.colls.cards).deleteMany({});
                    done();
                }).catch((err) => {
                    done(err);
                });
            });
            it("房间不存在", (done) => {
                co(function*() {
                    yield service.joinRoom(userInfo2.data.session, 123456);
                    done("应该要抛出房间不存在的错误");
                }).catch((err) => {
                    if (err.errcode == 202) {
                        done();
                    } else {
                        done(err);
                    }
                });
            });
            it("用户未登录", (done) => {
                co(function*() {
                    yield service.joinRoom("", 123456);
                    done("应该要抛出用户未登录的错误");
                }).catch((err) => {
                    if (err.errcode == 101) {
                        done();
                    } else {
                        done(err);
                    }
                });
            });
            it("已经在房间了", (done) => {
                co(function*() {
                    yield service.joinRoom(userInfo1.data.session, room.number);
                    done("应该要抛出已经在房间了的错误");
                }).catch((err) => {
                    if (err.errcode == 201) {
                        done();
                    } else {
                        done(err);
                    }
                });
            });
            it("加入房间直到房间人数已满", (done) => {
                co(function*() {
                    let result = yield service.joinRoom(userInfo2.data.session, room.number);
                    assert.equal(result.method, "joinRoom");
                    assert.equal(result.data.users.length, 2);
                    assert.equal(result.notifies.length, 1);
                    assert.equal(result.notifies[0].to, "1");
                    assert.equal(result.notifies[0].data.user.unionid, "2");
                    result = yield service.joinRoom(userInfo3.data.session, room.number);
                    assert.equal(result.data.users.length, 3);
                    assert.equal(result.notifies.length, 2);
                    assert.equal(result.notifies[0].to, "1");
                    assert.equal(result.notifies[0].method, "onNewJoinRoom");
                    assert.equal(result.notifies[1].to, "2");
                    assert.equal(result.notifies[1].method, "onNewJoinRoom");
                    assert.equal(result.notifies[0].data.user.unionid, "3");
                    assert.equal(result.notifies[1].data.user.unionid, "3");
                    yield db.collection(g.colls.users).updateOne({
                        unionid: "1"
                    }, {
                        $set: {
                            roomCard: 100
                        }
                    });
                    result = yield service.joinRoom(userInfo4.data.session, room.number);
                    for (let notify of result.notifies) {
                        if (notify.data.host == notify.to) {
                            assert.equal(notify.data.cards.length, 9, "庄家应当拿9张牌");
                            let _room = yield db.collection(g.colls.rooms).findOne({
                                number: room.number
                            });
                            let _ower = yield db.collection(g.colls.users).findOne({
                                unionid: room.owerId
                            });
                            let _host = yield db.collection(g.colls.users).findOne({
                                unionid: notify.data.host
                            });
                            let canDa = (() => {
                                for (let action of notify.data.actions) {
                                    if (Action.ACTIONS_DA == action.type) {
                                        return true;
                                    }
                                    return false;
                                }
                            })();
                            assert.equal(canDa, true, "庄家一定是可以打牌的");
                            assert.equal(_room.direction == _host.roomDirection, true, "当前房间的方向设置成庄家的方向");
                            assert.equal(_ower.roomCard, 99, "房主房卡数量-1");
                        } else {
                            assert.equal(notify.data.cards.length, 8);
                        }
                    }
                    yield service.joinRoom(userInfo7.data.session, room.number);
                    done("应该要抛出房间人数已满了的错误");
                }).catch((err) => {
                    if (err.errcode == 203) {
                        done();
                    } else {
                        done(err);
                    }
                });
            });
        });
    });
});
